/*
 * send_header.c
 * Created on November 29, 2005; 6:34 PM
 * by vramadurai
 */

/************ System Header Files ***************/
#include <stdio.h>
#include <stdlib.h>

/************ Private Header Files **************/
#include "HsTypes.h"
#include "PhyDebug.h"
#include "PhyStruct.h"
#include "PmdGlobals.h"
#include "PhyConstants.h"
#include "tables.h"
#include "tx_functions.h"
#include "iqdma_3500.h"
#include "icrdefs_3500.h"
#include "thread_globals.h"

void
send_header(
                struct HS_PhyTx11bStr  *volatile HS_PhyTx11bPtrTh1,
                hs_int16_t  * restrict ssDBPSKTbl,
                ePHYSTATES_TH  *ePhyState,
                hs_uint8_t *ucStateTable1Bit,
                hs_int16_t * psTxDtoAStartI,
                hs_int16_t * psTxDtoAStartQ,
                hs_uint16_t usDateRate,
                hs_uint8_t  * ucHeaderByte
             )
{
	hs_uint8_t ucBit;
    hs_int32_t subbuff_toggle;
    hs_uint16_t usDiffSymbIndex;
    hs_int32_t 	siHeaderBitCount;
    hs_int32_t 	siHeaderByteCount;
    hs_uint8_t 	ucByte=0;
    hs_uint8_t ucScramState;
    hs_uint8_t ucInputBit;
    hs_uint8_t ucPrevSymb;
    hs_int16_t 	* psTxOut;
    hs_int16_t 	* psTxOutDtoAPtrI;
    hs_int16_t 	* psTxOutDtoAPtrQ;

    hs_int32_t i;
    hs_int32_t estate = *ePhyState;

    ucScramState = HS_PhyTx11bPtrTh1->ucScramState;
	ucPrevSymb = HS_PhyTx11bPtrTh1->ucPrevSymb;

    siHeaderByteCount = 0;
    siHeaderBitCount = 0;

	psTxOutDtoAPtrI = HS_PhyTx11bPtrTh1->psTxDtoABufferI;
    psTxOutDtoAPtrQ = HS_PhyTx11bPtrTh1->psTxDtoABufferQ;

    subbuff_toggle = HS_PhyTx11bPtrTh1->subbuff_toggle;

    while(1){
    	START_CLOCK
    	for(i=0; i<8; i++){

	        if( (siHeaderBitCount & 0x7) == 0)
	        {
	           ucByte = ucHeaderByte[siHeaderByteCount];
	           siHeaderByteCount++;
	        }

	        ucBit = ucByte & 0x1;
	        ucByte >>= 1;
	        ucInputBit   = ucStateTable1Bit[ucScramState]^ucBit;
			ucScramState >>= 1;
			ucScramState |= (ucInputBit << 6);
			usDiffSymbIndex = ucPrevSymb^ucInputBit;
			ucPrevSymb = usDiffSymbIndex;

	        siHeaderBitCount++;

	        psTxOut = &(ssDBPSKTbl[usDiffSymbIndex*2*DUAL_BUF_QUARTER_SIZE]);

			__sb_rcopy(psTxOutDtoAPtrI, psTxOut);
			__sb_rcopy(psTxOutDtoAPtrI+16, psTxOut+16);
			__sb_rcopy(psTxOutDtoAPtrQ, psTxOut+24);
			__sb_rcopy(psTxOutDtoAPtrQ+16, psTxOut+24+16);

			psTxOutDtoAPtrI += (22);
			psTxOutDtoAPtrQ += (22);
    	}

    	if(siHeaderBitCount == 48){

        	if(usDateRate == TWO_MBPS)
    		{
    			if(ucPrevSymb){
                  ucPrevSymb = 2;
                }
                else{
                  ucPrevSymb = 1;
                }

                *ePhyState  = PHY_STATE_TX_SEND_PAYLOAD_2MBPS_TH;
                HS_PhyTx11bPtrTh1->ePhyState = *ePhyState;
            }
        	else if(usDateRate == FIVEDOTFIVE_MBPS)
    		{
    			if(ucPrevSymb){
                  ucPrevSymb = 2;
                }
                else{
                  ucPrevSymb = 1;
                }

                *ePhyState  = PHY_STATE_TX_SEND_PAYLOAD_5DOT5MBPS_TH;
                HS_PhyTx11bPtrTh1->ePhyState = *ePhyState;
            }
        	else if(usDateRate == ELEVEN_MBPS)
    		{
    			if(ucPrevSymb){
                  ucPrevSymb = 2;
                }
                else{
                  ucPrevSymb = 1;
                }

                *ePhyState  = PHY_STATE_TX_SEND_PAYLOAD_11MBPS_TH;
                HS_PhyTx11bPtrTh1->ePhyState = *ePhyState;
            }
        	else if(usDateRate == ONE_MBPS)
    		{
    			*ePhyState  = PHY_STATE_TX_SEND_PAYLOAD_1MBPS_TH;
    			HS_PhyTx11bPtrTh1->ePhyState = *ePhyState;
            }
        	else{

        	}
    	}

    	subbuff_toggle ^= 1;

		psTxOutDtoAPtrI = psTxDtoAStartI +
					  	  subbuff_toggle*SUB_BUF_SIZE_TX;
		psTxOutDtoAPtrQ = psTxDtoAStartQ +
					  	  subbuff_toggle*SUB_BUF_SIZE_TX;

		if(siHeaderBitCount == 48){
			HS_PhyTx11bPtrTh1->subbuff_toggle = subbuff_toggle;
		    HS_PhyTx11bPtrTh1->psTxDtoABufferI = psTxOutDtoAPtrI;
		    HS_PhyTx11bPtrTh1->psTxDtoABufferQ = psTxOutDtoAPtrQ;
		    HS_PhyTx11bPtrTh1->ucScramState = ucScramState;
			HS_PhyTx11bPtrTh1->ucPrevSymb = ucPrevSymb;

			tx_data_flag2 = 1;
			tx_data_flag3 = 1;
		}
		PRINT_CYCLES("send_header");
		/** Wait till prev sub-buffer is Txmitted **/
		#ifndef PHY_RX_CYCLE_PRINT
		wait_sub_buffer_filled();
		reset_sub_buffer_interrupt();
		#endif

        if(*ePhyState != estate)
            break;
    }
}


void
send_header_2mbps(
                struct HS_PhyTx11bStr  *HS_PhyTx11bPtrTh1,
                hs_int16_t  * restrict ssDQPSKTbl,
                hs_uint16_t *usDQPSKNew,
                ePHYSTATES_TH  *ePhyState,
                hs_uint8_t *ucStateTable2Bit,
                hs_int16_t * psTxDtoAStartI,
                hs_int16_t * psTxDtoAStartQ
             )
{
    hs_uint8_t ucBit;
    hs_uint16_t usDiffSymbIndex;
    hs_int32_t 	siHeaderBitCount;
    hs_int32_t 	siHeaderByteCount;
    hs_uint8_t 	ucByte=0;
    hs_int32_t 	estate;
    hs_uint8_t ucScramState;
    hs_uint8_t ucInputBit;
    hs_uint8_t ucPrevSymb;
    hs_int32_t symbol_count;
    hs_int32_t subbuff_toggle;
    hs_uint16_t usDateRate;
    hs_uint8_t  * ucHeaderByte;
    hs_int16_t 	* psTxOut;
    hs_int16_t 	* psTxOutDtoAPtrI;
    hs_int16_t 	* psTxOutDtoAPtrQ;

    estate = *ePhyState;

    subbuff_toggle = HS_PhyTx11bPtrTh1->subbuff_toggle;
    symbol_count = HS_PhyTx11bPtrTh1->symbol_count;
    usDateRate = HS_PhyTx11bPtrTh1->usDateRate;

    ucHeaderByte = HS_PhyTx11bPtrTh1->ucHeaderByte;
    ucScramState = HS_PhyTx11bPtrTh1->ucScramState;
	ucPrevSymb = HS_PhyTx11bPtrTh1->ucPrevSymb;

    siHeaderByteCount = 0;
    siHeaderBitCount = 0;

	psTxOutDtoAPtrI = HS_PhyTx11bPtrTh1->psTxDtoABufferI;
    psTxOutDtoAPtrQ = HS_PhyTx11bPtrTh1->psTxDtoABufferQ;

    while(1){

        if( (siHeaderBitCount & 0x7) == 0)
        {
           ucByte = ucHeaderByte[siHeaderByteCount];
           siHeaderByteCount++;
        }

        siHeaderBitCount += 2;

        ucBit = ucByte & 0x3;
        ucByte >>= 2;

        ucInputBit   = ucStateTable2Bit[ucScramState]^ucBit;
		ucScramState >>= 2;
		ucScramState |= (ucInputBit << 5);

		usDiffSymbIndex = usDQPSKNew[ucPrevSymb + (ucInputBit <<2)];
		ucPrevSymb = usDiffSymbIndex;

        if(siHeaderBitCount == 48){

            if(usDateRate  == TWO_MBPS){

                *ePhyState  = PHY_STATE_TX_SEND_PAYLOAD_2MBPS_TH;

            }
            else if(usDateRate  == FIVEDOTFIVE_MBPS){

                *ePhyState  = PHY_STATE_TX_SEND_PAYLOAD_5DOT5MBPS_TH;
            }
            else{
                *ePhyState  = PHY_STATE_TX_SEND_PAYLOAD_11MBPS_TH;
            }/* if usDateRate */
        }

        psTxOut = &(ssDQPSKTbl[usDiffSymbIndex*2*DUAL_BUF_QUARTER_SIZE]);

		__sb_rcopy(psTxOutDtoAPtrI, psTxOut);
		__sb_rcopy(psTxOutDtoAPtrI+16, psTxOut+16);
		__sb_rcopy(psTxOutDtoAPtrQ, psTxOut+24);
		__sb_rcopy(psTxOutDtoAPtrQ+16, psTxOut+24+16);

		psTxOutDtoAPtrI += (22);
		psTxOutDtoAPtrQ += (22);

		symbol_count++;
		if(symbol_count == 8){

			symbol_count = 0;

			/** Wait till prev sub-buffer is Txmitted **/
			wait_sub_buffer_filled();
			reset_sub_buffer_interrupt();

			subbuff_toggle ^= 1;
			psTxOutDtoAPtrI = psTxDtoAStartI +
						  	  subbuff_toggle*SUB_BUF_SIZE_TX;
			psTxOutDtoAPtrQ = psTxDtoAStartQ +
						  	  subbuff_toggle*SUB_BUF_SIZE_TX;
		}

        if(*ePhyState != estate)
            break;
    }

    HS_PhyTx11bPtrTh1->subbuff_toggle = subbuff_toggle;
	HS_PhyTx11bPtrTh1->symbol_count = symbol_count;
    HS_PhyTx11bPtrTh1->psTxDtoABufferI = psTxOutDtoAPtrI;
    HS_PhyTx11bPtrTh1->psTxDtoABufferQ = psTxOutDtoAPtrQ;
    HS_PhyTx11bPtrTh1->ucScramState = ucScramState;
	HS_PhyTx11bPtrTh1->ucPrevSymb = ucPrevSymb;
}

